home *** CD-ROM | disk | FTP | other *** search
/ Cream of the Crop 26 / Cream of the Crop 26.iso / program / vol16n13.zip / OPENTR.ZIP / OT_SRC.ZIP / MAINFRM.CPP < prev    next >
C/C++ Source or Header  |  1997-05-26  |  28KB  |  845 lines

  1. // MainFrm.cpp : implementation of the CMainFrame class
  2. //
  3. // OpenTrap Version 1.00 by Gregory A. Wolking
  4. // Copyright ⌐ 1997 Ziff-Davis Publishing
  5. // First published in PC Magazine, US Edition, July 1997.
  6.  
  7. #include "stdafx.h"
  8. #include <afxpriv.h>        // Required for definition of WM_KICKIDLE
  9. #include "OpenTrap.h"
  10.  
  11. #include "MainFrm.h"
  12. #include "OTDoc.h"
  13. #include "OTView.h"
  14. #include "OTextern.h"
  15. #include "OptDlg.h"
  16. #include "FiltDlg.h"
  17. #include "PageDlg.h"
  18. #include "ExpDlg.h"
  19. #ifdef _DEBUG
  20. #define new DEBUG_NEW
  21. #undef THIS_FILE
  22. static char THIS_FILE[] = __FILE__;
  23. #endif
  24.  
  25. #define WM_MY_STOP_LOG            (WM_USER + 1)    // Sent by VXD to signal log full.
  26. #define WM_MY_TASKBAR_NOTIFY    (WM_USER + 2)    // Used for Taskbar Notification messages.
  27.  
  28. // Text for taskbar icon tooltip.
  29. const char szTip_Text[] = "OpenTrap is logging -- double-click to activate";
  30.  
  31. /////////////////////////////////////////////////////////////////////////////
  32. // CMainFrame
  33.  
  34. IMPLEMENT_DYNCREATE(CMainFrame, CFrameWnd)
  35.  
  36. BEGIN_MESSAGE_MAP(CMainFrame, CFrameWnd)
  37.     //{{AFX_MSG_MAP(CMainFrame)
  38.     ON_WM_CREATE()
  39.     ON_WM_DESTROY()
  40.     ON_COMMAND(ID_LOGGING_START, OnLoggingStart)
  41.     ON_COMMAND(ID_LOGGING_STOP, OnLoggingStop)
  42.     ON_COMMAND(ID_LOGGING_OPTIONS, OnLoggingOptions)
  43.     ON_UPDATE_COMMAND_UI(ID_FILE_SAVE, OnUpdateFileSave)
  44.     ON_UPDATE_COMMAND_UI(ID_FILE_SAVE_AS, OnUpdateFileSaveAs)
  45.     ON_COMMAND(ID_FILE_EXPORT, OnFileExport)
  46.     ON_COMMAND(ID_VIEW_FILTER, OnViewFilter)
  47.     ON_COMMAND(ID_VIEW_RECNUM, OnViewRecnum)
  48.     ON_UPDATE_COMMAND_UI(ID_VIEW_RECNUM, OnUpdateViewRecnum)
  49.     ON_WM_CLOSE()
  50.     ON_UPDATE_COMMAND_UI(ID_FILE_PRINT, OnUpdateFilePrint)
  51.     ON_COMMAND(ID_VIEW_FONT, OnViewFont)
  52.     ON_COMMAND(ID_VIEW_FONT_DEFAULT, OnViewFontDefault)
  53.     ON_UPDATE_COMMAND_UI(ID_VIEW_FONT_DEFAULT, OnUpdateViewFontDefault)
  54.     ON_UPDATE_COMMAND_UI(ID_FILE_NEW, OnUpdateLogging)
  55.     ON_UPDATE_COMMAND_UI(ID_FILE_OPEN, OnUpdateLogging)
  56.     ON_UPDATE_COMMAND_UI(ID_FILE_EXPORT, OnUpdateFileSaveAs)
  57.     ON_UPDATE_COMMAND_UI(ID_VIEW_FILTER, OnUpdateLogging)
  58.     ON_UPDATE_COMMAND_UI(ID_FILE_PRINT_SETUP, OnUpdateLogging)
  59.     ON_WM_QUERYENDSESSION()
  60.     //}}AFX_MSG_MAP
  61.     // Global help commands
  62.     ON_COMMAND(ID_HELP_FINDER, CFrameWnd::OnHelpFinder)
  63.     ON_COMMAND(ID_HELP, CFrameWnd::OnHelp)
  64.     ON_COMMAND(ID_CONTEXT_HELP, CFrameWnd::OnContextHelp)
  65.     ON_COMMAND(ID_DEFAULT_HELP, CFrameWnd::OnHelpFinder)
  66.     ON_COMMAND_RANGE(ID_VIEW_TOP, ID_VIEW_GOTO, OnViewMove)
  67.     ON_COMMAND_EX(ID_VIEW_VIEWTOOLS, CFrameWnd::OnBarCheck)
  68.     ON_UPDATE_COMMAND_UI(ID_VIEW_VIEWTOOLS, CFrameWnd::OnUpdateControlBarMenu)
  69.     ON_UPDATE_COMMAND_UI_RANGE(ID_VIEW_TOP, ID_VIEW_GOTO, OnUpdateViewMove)
  70.     ON_UPDATE_COMMAND_UI_RANGE(ID_INDICATOR_IDLE, ID_INDICATOR_FILTER, OnUpdateIndicators)
  71.     ON_UPDATE_COMMAND_UI_RANGE(ID_LOGGING_START, ID_LOGGING_OPTIONS, OnUpdateLogging)
  72.     // User-defined messages
  73.     ON_MESSAGE(WM_MY_STOP_LOG, On_VXD_Stop_Request)
  74.     ON_MESSAGE(WM_MY_TASKBAR_NOTIFY, On_Taskbar_Notify)
  75. END_MESSAGE_MAP()
  76.  
  77. static UINT indicators[] =
  78. {
  79.     ID_SEPARATOR,           // status line indicator
  80.     ID_INDICATOR_IDLE,
  81.     ID_INDICATOR_FILTER,
  82.     ID_INDICATOR_POS
  83. };
  84. /////////////////////////////////////////////////////////////////////////////
  85. // CMainFrame construction/destruction
  86.  
  87. CMainFrame::CMainFrame()
  88. {
  89. }
  90.  
  91. CMainFrame::~CMainFrame()
  92. {
  93. }
  94.  
  95. int CMainFrame::OnCreate(LPCREATESTRUCT lpCreateStruct)
  96. {
  97.     if (CFrameWnd::OnCreate(lpCreateStruct) == -1)
  98.         return -1;
  99.     WINDOWPLACEMENT wp;
  100.     if (ReadWindowPlacement(&wp))
  101.         SetWindowPlacement(&wp);
  102.     if (!m_wndToolBar.Create(this) ||
  103.         !m_wndToolBar.LoadToolBar(IDR_MAINFRAME))
  104.     {
  105.         TRACE0("Failed to create toolbar\n");
  106.         return -1;      // fail to create
  107.     }
  108.     // When creating our Navigation toolbar, be sure to assign it the same ID
  109.     // as its menu command so we can hook it into the existing
  110.     // MFC toolbar/menu mechanism.
  111.     if (!m_wndViewToolBar.Create(this,
  112.             WS_CHILD | WS_VISIBLE | CBRS_TOP | CBRS_SIZE_DYNAMIC | CBRS_TOOLTIPS | CBRS_FLYBY, ID_VIEW_VIEWTOOLS) ||
  113.         !m_wndViewToolBar.LoadToolBar(IDR_VIEWTOOLS))
  114.     {
  115.         TRACE0("Failed to create toolbar\n");
  116.         return -1;      // fail to create
  117.     }
  118.  
  119.     if (!m_wndStatusBar.Create(this) ||
  120.         !m_wndStatusBar.SetIndicators(indicators,
  121.           sizeof(indicators)/sizeof(UINT)))
  122.     {
  123.         TRACE0("Failed to create status bar\n");
  124.         return -1;      // fail to create
  125.     }
  126.     // Make the toolbars dockable
  127.     m_wndToolBar.SetBarStyle(m_wndToolBar.GetBarStyle() |
  128.         CBRS_TOOLTIPS | CBRS_FLYBY | CBRS_SIZE_DYNAMIC);
  129.     m_wndViewToolBar.SetBarStyle(m_wndViewToolBar.GetBarStyle() |
  130.         CBRS_TOOLTIPS | CBRS_FLYBY | CBRS_SIZE_DYNAMIC);
  131.     m_wndToolBar.EnableDocking(CBRS_ALIGN_ANY);
  132.     m_wndToolBar.SetWindowText("File Tools");
  133.     m_wndViewToolBar.EnableDocking(CBRS_ALIGN_ANY);
  134.     m_wndViewToolBar.SetWindowText("Navigation Tools");
  135.     // Let toolbars dock anywhere
  136.     EnableDocking(CBRS_ALIGN_ANY);
  137.     // Attach the toolbars to the main window.
  138.     DockControlBar(&m_wndToolBar, AFX_IDW_DOCKBAR_TOP);
  139.     DockControlBarLeftOf(&m_wndViewToolBar, &m_wndToolBar);
  140.     // Read tool/status bar settings from the Registry.
  141.     LoadBarState("1.0\\Settings");
  142.     m_bInTaskBar = FALSE;
  143.     m_bVisible = TRUE;
  144.     return 0;
  145. }
  146.  
  147. BOOL CMainFrame::PreCreateWindow(CREATESTRUCT& cs)
  148. {
  149.     return CFrameWnd::PreCreateWindow(cs);
  150. }
  151.  
  152. /////////////////////////////////////////////////////////////////////////////
  153. // CMainFrame diagnostics
  154.  
  155. #ifdef _DEBUG
  156. void CMainFrame::AssertValid() const
  157. {
  158.     CFrameWnd::AssertValid();
  159. }
  160.  
  161. void CMainFrame::Dump(CDumpContext& dc) const
  162. {
  163.     CFrameWnd::Dump(dc);
  164. }
  165.  
  166. #endif //_DEBUG
  167.  
  168. /////////////////////////////////////////////////////////////////////////////
  169. // CMainFrame message handlers
  170.  
  171. // Windows messages.
  172.  
  173. // Called when user closes the main window.
  174. void CMainFrame::OnClose() 
  175. {
  176.     if (g_bIsLogging)            // If we're logging,
  177.     {
  178.         if (m_bInTaskBar)        // And the "hide to taskbar" option is enabled,
  179.         {
  180.             ShowWindow(SW_HIDE);    // just hide the main window.
  181.             m_bVisible = FALSE;
  182.             return;
  183.         }
  184.         // Otherwise, stop logging before the window closes.
  185.         if (AfxMessageBox(IDP_QUERY_LOG_STOP, MB_ICONQUESTION | MB_YESNO) == IDYES)
  186.             OnLoggingStop();
  187.         else
  188.             return;
  189.     }
  190.     // Kludge for saving Window position if minimized.
  191.     if (IsIconic())                    // If minimized,
  192.         ShowWindow(SW_RESTORE);        // Restore to normal position.
  193.     WINDOWPLACEMENT wp;                // Save window position.
  194.     wp.length = sizeof wp;
  195.     if (GetWindowPlacement(&wp))
  196.     {
  197.         wp.flags = 0;
  198.         if (IsZoomed())
  199.             wp.flags |= WPF_RESTORETOMAXIMIZED;
  200.         WriteWindowPlacement(&wp);
  201.     }
  202.     Do_Taskbar_Icon(NIM_DELETE);    // Kill taskbar icon.
  203.     CFrameWnd::OnClose();            // Call base class to close the window.
  204. }
  205.  
  206. // Called immediately before the main window is destroyed.
  207. // The window has already been removed from the screen, but it still exists.
  208. void CMainFrame::OnDestroy() 
  209. {
  210.     SaveBarState("1.0\\Settings");
  211.     if (g_bIsLogging)
  212.         Stop_Logging();
  213.     if (g_pBufferStart != NULL)
  214.     {
  215.         delete [] g_pBufferStart;
  216.         g_pBufferStart = NULL;
  217.     }
  218.     CFrameWnd::OnDestroy();
  219. }
  220.  
  221. // Called when Windows itself is shutting down.
  222. // This hook is necessary to ensure that logging stops and user is prompted
  223. // (if appropriate) to save the log before Windows exits.
  224. BOOL CMainFrame::OnQueryEndSession() 
  225. {
  226.     if (g_bIsLogging)            // If we're logging,
  227.         OnLoggingStop();        // stop.
  228.     // Call base class to save modified log if needed.
  229.     if (!CFrameWnd::OnQueryEndSession())
  230.         return FALSE;
  231.     return TRUE;
  232. }
  233.  
  234. ////////////////////////////////////
  235. // ToolBar and Menu command handlers
  236.  
  237. // Start Logging
  238. void CMainFrame::OnLoggingStart() 
  239. {
  240.     COpenTrapDoc *pDoc = (COpenTrapDoc *) GetActiveDocument();
  241.  
  242.     if (!g_bIsLogging)
  243.     {
  244.         m_intStartRecCount = g_intRecCount;        // Save current record count.
  245.         if (Start_Logging())                        // Try to start logging.
  246.         {
  247.             CString txt("OpenTrap [Logging to ");    // Set window caption if successful.
  248.             txt += pDoc->GetTitle();
  249.             txt += "]";
  250.             SetWindowText(txt);
  251.             if (g_bHide)
  252.             {
  253.                 Do_Taskbar_Icon(NIM_ADD);
  254.                 m_bInTaskBar = TRUE;
  255.                 ShowWindow(SW_HIDE);
  256.                 m_bVisible = FALSE;
  257.             }
  258.         }
  259.         else
  260.             AfxMessageBox(IDP_LOG_START_FAIL, MB_OK, 0);    // Error message if not;
  261.     }
  262.     pDoc->UpdateAllViews(NULL, 0, 0);    // Update the display.
  263. }
  264.  
  265. // Stop Logging
  266. void CMainFrame::OnLoggingStop() 
  267. {
  268.     COpenTrapDoc *pDoc = (COpenTrapDoc *) GetActiveDocument();
  269.  
  270.     if (g_bIsLogging)
  271.     {
  272.         CString txt("OpenTrap - ");        // Reset Window caption.
  273.         txt += pDoc->GetTitle();
  274.         Stop_Logging();                    // Turn off the thread.
  275.         SetWindowText(txt);                // Reset Window caption.
  276.         if (m_bInTaskBar)
  277.         {
  278.             Do_Taskbar_Icon(NIM_DELETE);
  279.             if (!IsWindowVisible())
  280.                 ShowWindow(SW_SHOW);
  281.             m_bInTaskBar = FALSE;
  282.             m_bVisible = TRUE;
  283.         }
  284.     }
  285.     if (g_intRecCount != m_intStartRecCount)    // If any records were captured,
  286.     {
  287.         pDoc->SetModifiedFlag();                // Mark the document as dirty.
  288.         pDoc->Fix_Pointers(g_intRecCount);        // Rebuild list pointers.
  289.     }
  290.     pDoc->UpdateAllViews(NULL, 0, 0);    // Update the display.
  291. }
  292.  
  293. // Presents the Logging Options dialog.
  294. void CMainFrame::OnLoggingOptions() 
  295. {
  296.     COptDlg dlg;
  297.  
  298.     // Set dialog controls to match current settings.
  299.     dlg.m_bHide = g_bHide;
  300.     dlg.m_bErrorsOnly = g_bLogErrorsOnly;
  301.     dlg.m_intAction = (g_bLogOpensOnly) ? 1 : 0;
  302.     dlg.m_intLogSize = g_intLogSizeK;
  303.     if (g_dwWatchVM == LOG_ALL)
  304.         dlg.m_intVM = 0;
  305.     else
  306.         dlg.m_intVM = ((g_dwWatchVM == LOG_WINDOWS_ONLY) ? 1 : 2);
  307.     if (dlg.DoModal() == IDOK)    // Launch the dialog. If user says OK,
  308.     {
  309.         g_bHide = dlg.m_bHide;
  310.         g_bLogErrorsOnly = dlg.m_bErrorsOnly;        // Set options from the
  311.         g_bLogOpensOnly = dlg.m_intAction == 1;        // dialog.
  312.         switch (dlg.m_intVM)
  313.         {
  314.         case 0:
  315.             g_dwWatchVM = LOG_ALL;
  316.             break;
  317.         case 1:
  318.             g_dwWatchVM = LOG_WINDOWS_ONLY;
  319.             break;
  320.         case 2:
  321.             g_dwWatchVM = LOG_ALL_DOS;
  322.         }
  323.         if (dlg.m_intLogSize != g_intLogSizeK)        // Did user change the buffer size?
  324.         {
  325.             void * new_buf;                            // Try to reallocate it if so.
  326.             new_buf = realloc(g_pBufferStart, (dlg.m_intLogSize * 1024));
  327.             if (new_buf)
  328.             {
  329.                 g_intLogSizeK = dlg.m_intLogSize;        // If successful, save new log size.
  330.                 g_pBufferStart = (char *) new_buf;    // Update buffer start pointer.
  331.                                                     // realloc() may have moved the buffer
  332.                 if (g_intRecCount)                    // so if it's not empty, fix the pointer chain.
  333.                     ((COpenTrapDoc *) GetActiveDocument())->Fix_Pointers(g_intRecCount);
  334.                 else
  335.                     g_pNextRec = g_pBufferStart;    // Otherwise just end equal to start.
  336.                 // Calculate "safe" end of buffer for VXD, leaving enough room for
  337.                 // the largest possible event record.
  338.                 g_pBufSafeEnd = (g_pBufferStart + (g_intLogSizeK * 1024) - (sizeof(packed_record) + MAX_PATH + 2));
  339.                 // Set full flag if not enough room for another record.
  340.                 g_bLogFull = g_pNextRec > g_pBufSafeEnd;
  341.             }
  342.             else
  343.                 MessageBox("Reallocation failed\nBuffer remains unchanged", "OpenTrap", MB_OK);
  344.         }
  345.         // Save settings if requested.
  346.         if (dlg.m_bSaveSettings)
  347.         {
  348.             CWinApp* myApp = AfxGetApp();
  349.             myApp->WriteProfileInt(g_szLogKey, "BufferSizeK", g_intLogSizeK);
  350.             myApp->WriteProfileInt(g_szLogKey, "LogErrorsOnly", g_bLogErrorsOnly);
  351.             myApp->WriteProfileInt(g_szLogKey, "LogActions", g_bLogOpensOnly);
  352.             myApp->WriteProfileInt(g_szLogKey, "WatchVMs", g_dwWatchVM);
  353.             myApp->WriteProfileInt(g_szLogKey, "UseTaskBar", g_bHide);
  354.         }
  355.     }
  356. }
  357.  
  358. // Presents the Export Options dialog and, if requested,
  359. // writes a text file in the desired format.
  360. void CMainFrame::OnFileExport() 
  361. {
  362.     COpenTrapDoc * pDoc = (COpenTrapDoc *) GetActiveDocument();
  363.     CString t;
  364.     int p;
  365.     CExpDlg dlg;                                    // Create the dialog.
  366.  
  367.     dlg.m_bUseFilters = g_bWriteFiltered;            // Initialize member variables.
  368.     dlg.m_bRecNums = g_bExportRecNums;
  369.     dlg.m_intFormat = g_bCommaDelimited ? 1 : 0;
  370.     if (dlg.DoModal() != IDOK)                        // Launch the dialog.
  371.         return;                                        // Done if user didn't say OK.
  372.  
  373.     g_bWriteFiltered = dlg.m_bUseFilters;            // Retrieve settings from dialog.
  374.     g_bCommaDelimited = dlg.m_intFormat == 1;
  375.     g_bExportRecNums = dlg.m_bRecNums;
  376.     t = pDoc->GetTitle();                            // Get document name.
  377.     while ((p = t.ReverseFind('.')) != -1)            // Strip off extension.
  378.         t = t.Left(p);
  379.     CFileDialog cf(FALSE,                            // Create a Save As dialog.
  380.         ".txt",                                        // Default extension if none specified.
  381.         (LPCTSTR) t,                                // Default base filename.
  382.         OFN_HIDEREADONLY | OFN_OVERWRITEPROMPT,        // No read-only, prompt before overwrite.
  383.         "Text log files (*.txt)|*.txt|All Files (*.*)|*.*||",    // File filters.
  384.         this);
  385.     if (cf.DoModal() == IDOK)                        // Launch dialog. If user said OK,
  386.         pDoc->Write_Text_Log(cf.GetPathName());        // write text log to the specified file.
  387. }
  388.  
  389. // Presents the Filter Options dialog.
  390. void CMainFrame::OnViewFilter() 
  391. {
  392.     COpenTrapDoc * pDoc = (COpenTrapDoc *) GetActiveDocument();
  393.     CFilterDlg dlg;                                        // Create the dialog
  394.  
  395.     dlg.m_bSaveSettings = FALSE;                        // Initialize member variables.
  396.     dlg.m_bBaseName = g_bFilterFileName;
  397.     dlg.m_strBaseName = g_strFilterFileName;
  398.     dlg.m_bExt = g_bFilterFileExt;
  399.     dlg.m_strExt = g_strFilterFileExt;
  400.     dlg.m_bModuleName = g_bFilterModule;
  401.     dlg.m_strModuleName = g_strFilterModuleName;
  402.     dlg.m_intShow = g_intFilterEvents;
  403.     dlg.m_bErrorsOnly = g_bFilterErrorsOnly;
  404.     if (dlg.DoModal() == IDOK)                            // Launch the dialog. If user said OK,
  405.     {
  406.         g_bFilterFileName = dlg.m_bBaseName;            // Transfer settings from dialog to global.
  407.         g_strFilterFileName = dlg.m_strBaseName;
  408.         g_bFilterFileExt = dlg.m_bExt;
  409.         g_strFilterFileExt = dlg.m_strExt;
  410.         g_bFilterModule = dlg.m_bModuleName;
  411.         g_strFilterModuleName = dlg.m_strModuleName;
  412.         g_intFilterEvents = dlg.m_intShow;
  413.         g_bFilterErrorsOnly = dlg.m_bErrorsOnly;
  414.         pDoc->SetFilterFlag();
  415.         if (dlg.m_bSaveSettings)                        // If user checked the Save Settings box,
  416.         {
  417.             CWinApp * myApp = AfxGetApp();                // Write new settings to the Registry.
  418.             myApp->WriteProfileInt(g_szViewKey, "UseBase", g_bFilterFileName);
  419.             myApp->WriteProfileString(g_szViewKey, "Base", g_strFilterFileName);
  420.             myApp->WriteProfileInt(g_szViewKey, "UseExt", g_bFilterFileExt);
  421.             myApp->WriteProfileString(g_szViewKey, "Ext", g_strFilterFileExt);
  422.             myApp->WriteProfileInt(g_szViewKey, "UseModule", g_bFilterModule);
  423.             myApp->WriteProfileString(g_szViewKey, "Module", g_strFilterModuleName);
  424.             myApp->WriteProfileInt(g_szViewKey, "Events", g_intFilterEvents);
  425.             myApp->WriteProfileInt(g_szViewKey, "Errors", g_bFilterErrorsOnly);
  426.         }
  427.         if (g_intRecCount)                                // If log is not empty,
  428.             pDoc->UpdateAllViews(NULL, FALSE, NULL);    // Redraw the display with the new filters.
  429.     }
  430. }
  431.  
  432. // Turns Record Number display on and off.
  433. void CMainFrame::OnViewRecnum() 
  434. {
  435.     COpenTrapDoc* pDoc = (COpenTrapDoc*)GetActiveDocument();
  436.  
  437.     g_bShowNums = !g_bShowNums;
  438.     if (g_intRecCount)
  439.         pDoc->UpdateAllViews(NULL, TRUE, NULL);
  440. }
  441.  
  442. // Handles navigation commands
  443. void CMainFrame::OnViewMove(UINT nID)
  444. {
  445.     COpenTrapView* pView = (COpenTrapView*)GetActiveView();
  446.     COpenTrapDoc* pDoc = pView->GetDocument();
  447.     int response = IDOK;
  448.  
  449.     switch (nID)
  450.     {
  451.     case ID_VIEW_TOP:
  452.         pView->m_intCurrent_Page = 1;
  453.         pView->SetScrollPos(SB_VERT, 0, FALSE);
  454.         break;
  455.     case ID_VIEW_PREVIOUS:
  456.         --pView->m_intCurrent_Page;
  457.         break;
  458.     case ID_VIEW_NEXT:
  459.         ++pView->m_intCurrent_Page;
  460.         pView->SetScrollPos(SB_VERT, 0, FALSE);
  461.         break;
  462.     case ID_VIEW_LAST:
  463.         pView->m_intCurrent_Page = pView->m_intPage_Count;
  464.         pView->SetScrollPos(SB_VERT, 0, FALSE);
  465.         break;
  466.     case ID_VIEW_GOTO:
  467.         CPageDlg dlg;
  468.         dlg.m_intEndPage = pView->m_intPage_Count;
  469.         dlg.m_intPageNum = pView->m_intCurrent_Page;
  470.         if ((response = dlg.DoModal()) == IDOK)
  471.             pView->m_intCurrent_Page = dlg.m_intPageNum;
  472.     }
  473.     if (response == IDOK)
  474.         pDoc->UpdateAllViews(NULL, nID, NULL);
  475. }
  476.  
  477. // Presents font dialog and attaches new font if necessary.
  478. void CMainFrame::OnViewFont() 
  479. {
  480.     LOGFONT my_font, *pMyFont;
  481.     COpenTrapView* pView = (COpenTrapView*)GetActiveView();
  482.     COpenTrapDoc* pDoc = (COpenTrapDoc*)GetActiveDocument();
  483.  
  484.     if (pView->m_fontCustom)        // Already using custom font?
  485.     {
  486.         pMyFont = &my_font;                            // Point to our LOGFONT structure.
  487.         pView->m_fontCustom->GetLogFont(pMyFont);    // Load it from the custom font.
  488.     }
  489.     else
  490.         pMyFont = NULL;                // Otherwise, dialog comes up with no font selected.
  491.     CFontDialog dlg(pMyFont, CF_SCREENFONTS | CF_TTONLY, NULL, this);
  492.     if (dlg.DoModal() != IDOK)
  493.         return;        // Nothing to do if user didn't OK the dialog
  494.     // Retrieve font data from the dialog.
  495.     // NOTE: The MFC documentation says you can use CFontDialog::GetCurrentSelection(), but
  496.     // it fails; it only works while the dialog is active, not after DoModal() returns!
  497.     memcpy(&my_font, dlg.m_cf.lpLogFont, sizeof(dlg.m_lf));
  498.     if (pView->m_fontCustom)            // If custom font was in use,
  499.         delete pView->m_fontCustom;        // delete it.
  500.     pView->m_fontCustom = new CFont;    // Create new CFont object.
  501.     pView->m_fontCustom->CreateFontIndirect(&my_font);    // Load it with desired font.
  502.     pDoc->UpdateAllViews(NULL);            // Update the display.
  503. }
  504.  
  505. // Reverts to default system font.
  506. void CMainFrame::OnViewFontDefault() 
  507. {
  508.     COpenTrapView* pView = (COpenTrapView *)GetActiveView();
  509.     COpenTrapDoc* pDoc = (COpenTrapDoc*)GetActiveDocument();
  510.     if (pView->m_fontCustom)
  511.     {
  512.         delete pView->m_fontCustom;
  513.         pView->m_fontCustom = NULL;
  514.         pDoc->UpdateAllViews(NULL);
  515.     }
  516. }
  517.  
  518. /////////////////////////////
  519. // Custom message handlers
  520.  
  521. // Handles WM_MY_STOP_LOG message posted by callback function when buffer fills.
  522. LONG CMainFrame::On_VXD_Stop_Request(WPARAM wParam, LPARAM lParam)
  523. {
  524.     OnLoggingStop();
  525.     return 0L;
  526. }
  527.  
  528. // Handles notification messages from our task bar icon.
  529. // Note: We only have one icon on the taskbar, so we can
  530. // ignore the icon identifier (wParam).
  531. LONG CMainFrame::On_Taskbar_Notify(WPARAM wParam, LPARAM lParam)
  532. {
  533.     if (!m_bVisible)        // Ignore taskbar if we're already visible.
  534.     {
  535.         if (lParam == WM_LBUTTONDBLCLK)        // Double click?
  536.         {
  537.             ShowWindow(SW_SHOW);            // Restore the window
  538.             m_bVisible = TRUE;                // Set flag.
  539.             PostMessage(WM_KICKIDLE, 0, 0);    // Force command UI update.
  540.         }
  541.     }
  542.     return 0L;    // Let the system know that we processed the message.
  543. }
  544.  
  545. ///////////////////////
  546. // User interface update handlers
  547. // These handlers are responsible for enabling and disabling various controls
  548. // (menu commands and toolbar buttons) based on the program's current state.
  549.  
  550. void CMainFrame::OnUpdateViewFontDefault(CCmdUI* pCmdUI) 
  551. {
  552.     COpenTrapView* pView = (COpenTrapView *)GetActiveView();
  553.     pCmdUI->Enable(pView->m_fontCustom != NULL);
  554. }
  555.  
  556. void CMainFrame::OnUpdateLogging(CCmdUI* pCmdUI)
  557. {
  558.     switch (pCmdUI->m_nID)
  559.     {
  560.     case ID_LOGGING_STOP: pCmdUI->Enable(g_bIsLogging);    break;
  561.  
  562.     case ID_LOGGING_OPTIONS:
  563.     case ID_FILE_NEW:
  564.     case ID_FILE_OPEN:
  565.     case ID_FILE_PRINT_SETUP:
  566.     case ID_VIEW_FILTER: pCmdUI->Enable(!g_bIsLogging);    break;
  567.  
  568.     case ID_LOGGING_START:
  569.         pCmdUI->Enable(!g_bIsLogging && !g_bLogFull);
  570.         if (g_intRecCount == 0)
  571.             pCmdUI->SetText("Start &Logging");
  572.         else
  573.             pCmdUI->SetText("Resume &Logging");
  574.     }
  575. }
  576.  
  577. void CMainFrame::OnUpdateFileSave(CCmdUI* pCmdUI) 
  578. {
  579.     pCmdUI->Enable((!g_bIsLogging) && (g_intRecCount > 0) && GetActiveDocument()->IsModified());
  580. }
  581.  
  582. void CMainFrame::OnUpdateFileSaveAs(CCmdUI* pCmdUI) 
  583. {
  584.     pCmdUI->Enable((!g_bIsLogging) && (g_intRecCount > 0));
  585. }
  586.  
  587. void CMainFrame::OnUpdateViewRecnum(CCmdUI* pCmdUI) 
  588. {
  589.     pCmdUI->SetCheck(g_bShowNums);
  590.     pCmdUI->Enable(!g_bIsLogging);
  591. }
  592.  
  593. void CMainFrame::OnUpdateViewMove(CCmdUI* pCmdUI)
  594. {
  595.     if (g_bIsLogging || g_intRecCount == 0)
  596.     {
  597.         pCmdUI->Enable(FALSE);
  598.         return;
  599.     }
  600.  
  601.     COpenTrapView* pView = (COpenTrapView*)GetActiveView();
  602.     BOOL status = FALSE;
  603.     switch (pCmdUI->m_nID)
  604.     {
  605.     case ID_VIEW_TOP:
  606.     case ID_VIEW_PREVIOUS:    status = pView->m_intCurrent_Page > 1; break;
  607.     case ID_VIEW_LAST:
  608.     case ID_VIEW_NEXT:        status = pView->m_intCurrent_Page < pView->m_intPage_Count; break;
  609.     case ID_VIEW_GOTO:        status = pView->m_intPage_Count > 1;
  610.     }
  611.     pCmdUI->Enable(status);
  612. }
  613.  
  614. void CMainFrame::OnUpdateFilePrint(CCmdUI* pCmdUI) 
  615. {
  616.     COpenTrapView* pView = (COpenTrapView*)GetActiveView();
  617.     pCmdUI->Enable((!g_bIsLogging) && (g_intRecCount > 0) && (pView->m_intFilt_Rec_Count > 0));
  618. }
  619.  
  620. // This function sets the text for the Status Bar display.
  621. void CMainFrame::OnUpdateIndicators(CCmdUI* pCmdUI)
  622. {
  623.     switch (pCmdUI->m_nID)
  624.     {
  625.     case ID_INDICATOR_FILTER:
  626.         pCmdUI->Enable(g_bUseFilters);
  627.         break;
  628.     // The "Position" field serves multiple duties depending on the current mode.
  629.     // While logging, it indicates the approximate number of records in the buffer.
  630.     // While idle, it shows either the current page number or "Log is empty".
  631.     case ID_INDICATOR_POS:
  632.         {
  633.             CString txt;
  634.             if (g_bIsLogging)
  635.             {
  636.                 txt.Format("%u records captured", g_intRecCount);
  637.             }
  638.             else
  639.             {
  640.                 pCmdUI->Enable(TRUE);
  641.                 if (g_intRecCount == 0)
  642.                     txt = "Log is empty";
  643.                 else
  644.                 {
  645.                     COpenTrapView * pView = (COpenTrapView*)GetActiveView();
  646.                     if (pView->m_intFilt_Rec_Count == 0)
  647.                         txt.Format("%u records on file", g_intRecCount);
  648.                     else
  649.                         txt.Format("Page %u of %u", pView->m_intCurrent_Page, pView->m_intPage_Count);
  650.                 }
  651.             }
  652.             pCmdUI->SetText(txt);
  653.         }
  654.         break;
  655.     case ID_INDICATOR_IDLE:
  656.         if (g_bIsLogging)
  657.             pCmdUI->SetText("LOGGING");
  658.         else
  659.         {
  660.             if (g_bLogFull)
  661.                 pCmdUI->SetText("LOG FULL");
  662.             else
  663.                 pCmdUI->SetText("IDLE");
  664.         }
  665.     }
  666. }
  667.  
  668. ////////////////////////////
  669. // Helper functions.
  670.  
  671. // Loads FUNCTRAP.VXD and launches logging thread.
  672. // Returns TRUE if logging started successfully.
  673. // Returns FALSE and displays appropriate error message if:
  674. //        1. Unable to load FUNCTRAP.VXD
  675. //        2. Unable to launch logging thread.
  676. BOOL CMainFrame::Start_Logging(void)
  677. {
  678.  
  679.     // Open the handle to the VXD
  680.     g_hVXD = CreateFile( VXD_NAME, 0, 0, NULL, 0, FILE_FLAG_DELETE_ON_CLOSE, NULL );
  681.     if ( g_hVXD == INVALID_HANDLE_VALUE )
  682.     {
  683.         AfxMessageBox(IDP_VXD_LOAD_FAIL, MB_ICONINFORMATION);
  684.         return FALSE;
  685.     }
  686.     // Calculate safe end of buffer to prevent overruns.
  687.     g_pBufSafeEnd = g_pBufferStart + ((g_intLogSizeK * 1024) - 400);
  688.     // Initialize the VXD.
  689.     DeviceIoControl(g_hVXD, VXD_GET_VER, g_pBufferStart, 4, NULL, 0, NULL, NULL );
  690.     // Initialize trap condition records.
  691.     g_tcCond1.tc_callback = g_tcCond2.tc_callback = (DWORD) &our_callback;
  692.     g_tcCond1.tc_misc = g_tcCond2.tc_misc = 0;
  693.     g_tcCond1.tc_vm_num = g_tcCond2.tc_vm_num = g_dwWatchVM;
  694.     // Create Critical Section and Event objects used to control worker thread.
  695.      InitializeCriticalSection(&g_csCritical);
  696.     g_hStopFlag = CreateEvent(NULL, FALSE, FALSE, NULL); 
  697.     ResetEvent(g_hStopFlag);
  698.     // Launch the worker thread.
  699.     g_hThread=(HANDLE) _beginthreadex(NULL, 4096,(unsigned int (__stdcall *) (void *)) do_getcalls,
  700.                 NULL, 0,(unsigned int *) &g_dwThreadID);
  701.     // Reset and display error message if thread launch failed.
  702.     if (g_hThread == (HANDLE) 0)
  703.     {
  704.         CloseHandle(g_hVXD);                            // Release VXD
  705.         CloseHandle(g_hStopFlag);                        // Release event object.
  706.         AfxMessageBox(IDP_THREAD_FAIL, MB_ICONSTOP);    // Show error message
  707.     }
  708.     return (g_bIsLogging = (g_hThread != (HANDLE) 0));    // Return logging status to caller.
  709. }
  710.  
  711. // Signals VxD to stop logging, terminates logging thread, and releases VxD.
  712. void CMainFrame::Stop_Logging(void)
  713. {
  714.     // First, tell the VXD to stop recording events.
  715.     g_ucUpdate.trap_rec_num    = g_dwCondition1;
  716.     g_ucUpdate.trap_dat_ptr    = (DWORD) &g_tcCond1;
  717.     g_ucUpdate.trap_dat_len    = sizeof(struct trap_criteria);
  718.     g_tcCond1.tc_misc        = (APP_EXITING | DISABLE_LOGGING);    // Tells VXD to release this record.
  719.     DeviceIoControl(g_hVXD, VXD_UPDATE, &g_ucUpdate,
  720.                (sizeof(struct upcall)), NULL, 0, NULL, NULL );
  721.     if (!g_bLogOpensOnly)    // 2nd condition record is not used if logging opens only.
  722.     {
  723.         g_ucUpdate.trap_rec_num    = g_dwCondition2;
  724.         g_ucUpdate.trap_dat_ptr    = (DWORD) &g_tcCond2;
  725.         g_ucUpdate.trap_dat_len    = sizeof(struct trap_criteria);
  726.         g_tcCond2.tc_misc        = (APP_EXITING | DISABLE_LOGGING);
  727.         DeviceIoControl(g_hVXD, VXD_UPDATE, &g_ucUpdate,
  728.                (sizeof(struct upcall)), NULL, 0, NULL, NULL );
  729.     }
  730.     CloseHandle(g_hVXD);                // Release VXD
  731.     SetEvent(g_hStopFlag);                // Tell logging thread to stop
  732.     CloseHandle(g_hThread);                // Clean up associated handles and structure.
  733.     CloseHandle(g_hStopFlag);
  734.     DeleteCriticalSection(&g_csCritical);
  735.     g_bIsLogging = FALSE;                // Set logging status.
  736. }
  737.  
  738.  
  739. // Adds or deletes our task bar icon.
  740. // Input: func = NIM_ADD or NIM_DELETE.
  741. // Returns: TRUE = success
  742. //            FALSE = failure.
  743. BOOL CMainFrame::Do_Taskbar_Icon(UINT func)
  744. {
  745.     NOTIFYICONDATA tnid;
  746.     BOOL result;
  747.  
  748.     // Initialize common members of TNID structure.
  749.     tnid.cbSize = sizeof(tnid);
  750.     tnid.hWnd = m_hWnd;
  751.     tnid.uID = IDR_MAINFRAME;
  752.     tnid.uFlags = 0;
  753.     // Set remaining members based on task to be performed.
  754.     switch (func)
  755.     {
  756.     case NIM_ADD:        // Add new icon.
  757.         tnid.uFlags = NIF_MESSAGE | NIF_ICON | NIF_TIP;        // Signal all members valid.
  758.         tnid.uCallbackMessage = WM_MY_TASKBAR_NOTIFY;        // Set callback message identifier.
  759.         // Note: Use LoadImage to make sure we get the small (16 x 16) icon.
  760.         tnid.hIcon = (HICON) LoadImage(    AfxGetApp()->m_hInstance,
  761.                                         MAKEINTRESOURCE(IDR_MAINFRAME),
  762.                                         IMAGE_ICON,
  763.                                         16,
  764.                                         16,
  765.                                         LR_DEFAULTCOLOR);
  766.         break;
  767.     case NIM_DELETE:    // Remove existing icon.
  768.         tnid.hIcon = NULL;                                    // Don't need icon handle for removal.
  769.     }
  770.     // Set tooltip text if needed.
  771.     if (func == NIM_ADD)
  772.         lstrcpyn(tnid.szTip, szTip_Text, sizeof(tnid.szTip));
  773.     // Call API, return success or failure to caller.
  774.     result = Shell_NotifyIcon(func, &tnid);
  775.     // Discard the icon if it was loaded
  776.     // (Shell_NotifyIcon makes its own copy of the image, so we don't have to waste memory for it).
  777.     if (tnid.hIcon)
  778.         DestroyIcon(tnid.hIcon);
  779.     return result;
  780. }
  781.  
  782. /////////////////////////////////////////////////////////////////////////////
  783. // Helpers for saving/restoring window state
  784. // Note that these were lifted verbatim from MFC samples.
  785. BOOL CMainFrame::ReadWindowPlacement(LPWINDOWPLACEMENT pwp)
  786. {
  787.     CString strBuffer = AfxGetApp()->GetProfileString(g_szSettingKey, "WindowPos");
  788.     if (strBuffer.IsEmpty())
  789.         return FALSE;
  790.  
  791.     WINDOWPLACEMENT wp;
  792.     int nRead = _stscanf(strBuffer, g_szFormat,
  793.         &wp.flags, &wp.showCmd,
  794.         &wp.ptMinPosition.x, &wp.ptMinPosition.y,
  795.         &wp.ptMaxPosition.x, &wp.ptMaxPosition.y,
  796.         &wp.rcNormalPosition.left, &wp.rcNormalPosition.top,
  797.         &wp.rcNormalPosition.right, &wp.rcNormalPosition.bottom);
  798.  
  799.     if (nRead != 10)
  800.         return FALSE;
  801.  
  802.     wp.length = sizeof wp;
  803.     *pwp = wp;
  804.     return TRUE;
  805. }
  806.  
  807. void CMainFrame::WriteWindowPlacement(LPWINDOWPLACEMENT pwp)
  808.     // write a window placement to settings section of app's ini file
  809. {
  810.     TCHAR szBuffer[sizeof("-32767")*8 + sizeof("65535")*2];
  811.  
  812.     wsprintf(szBuffer, g_szFormat,
  813.         pwp->flags, pwp->showCmd,
  814.         pwp->ptMinPosition.x, pwp->ptMinPosition.y,
  815.         pwp->ptMaxPosition.x, pwp->ptMaxPosition.y,
  816.         pwp->rcNormalPosition.left, pwp->rcNormalPosition.top,
  817.         pwp->rcNormalPosition.right, pwp->rcNormalPosition.bottom);
  818.     AfxGetApp()->WriteProfileString(g_szSettingKey, "WindowPos", szBuffer);
  819. }
  820.  
  821. // Helper function for setting initial toolbar position.
  822. void CMainFrame::DockControlBarLeftOf(CToolBar* Bar, CToolBar* LeftOf)
  823. {
  824.     CRect rect;
  825.     DWORD dw;
  826.     UINT n;
  827.  
  828.     // get MFC to adjust the dimensions of all docked ToolBars
  829.     // so that GetWindowRect will be accurate
  830.     RecalcLayout();
  831.     LeftOf->GetWindowRect(&rect);
  832.     rect.OffsetRect(1, 0);
  833.     dw=LeftOf->GetBarStyle();
  834.     n = 0;
  835.     n = (dw & CBRS_ALIGN_TOP) ? AFX_IDW_DOCKBAR_TOP : n;
  836.     n = (dw & CBRS_ALIGN_BOTTOM && n==0) ? AFX_IDW_DOCKBAR_BOTTOM : n;
  837.     n = (dw & CBRS_ALIGN_LEFT && n==0) ? AFX_IDW_DOCKBAR_LEFT : n;
  838.     n = (dw & CBRS_ALIGN_RIGHT && n==0) ? AFX_IDW_DOCKBAR_RIGHT : n;
  839.  
  840.     // When we take the default parameters on rect, DockControlBar will dock
  841.     // each Toolbar on a separate line.  By calculating a rectangle, we in effect
  842.     // are simulating a Toolbar being dragged to that location and docked.
  843.     DockControlBar(Bar, n, &rect);
  844. }
  845.